// utils/websocket.js
export default class WebsocketTask {
  /** 心跳定时器 */
  #heartbeatInterval = null
  /** 回调函数 */
  #callback = null
  /** ws状态 */
  #websocketStatus = false
  /** 是否主动关闭 */
  #isClosed = false

  constructor(url, interval) {
    this.url = url
    this.intervalTime = interval

    // 实例化时立即连接ws。根据需求启用
    // try {
    //     return this.initWebsocket()
    // } catch (e) {
    //     this.#websocketStatus = false
    //     this.reconnect()
    // }
  }

  /**
   * 初始化Websocket
   */
  initWebsocket() {
    this.socketTask = uni.connectSocket({
      url: this.url,
      // 必要，否则会返回一个Promise
      success: (status) => {}
    })

    this.socketTask.onOpen(() => {
      clearTimeout(this.#heartbeatInterval)
      this.#isClosed = false
      this.#startHeartbeat()
      this.socketTask.onMessage((msg) => {
        let msgObj = JSON.parse(msg.data) || null

        if (msgObj.type === 'pong') {
          if (this.#websocketStatus === false) console.log('%c [Websocket] ', 'background: #2888D9;', '初始化成功')
          this.#websocketStatus = true
        } else {
          console.log('%c [Websocket] ', 'background: #2888D9;', '接收消息:', msgObj)
          this.#callback && this.#callback(msgObj)
        }
      })
    })

    // Websocket Closed Unexpected
    this.socketTask.onClose(() => {
      this.#websocketStatus = false
      console.log('%c [Websocket] ', 'background: #2888D9;', '断开连接!')
      // 非主动断开时自动重连
      if (!this.#isClosed) this.reconnect()
    })
  }

  /** 开始心跳 */
  #startHeartbeat() {
    this.#heartbeatInterval = setInterval(() => {
      this.sendMessage({
        type: 'ping'
      })
    }, this.intervalTime)
  }

  /**
   * 发送消息
   * @param {*} data 消息内容
   */
  sendMessage(data) {
    if (data.type !== 'ping') {
      // 未就绪时稍后重试
      if (!this.#websocketStatus) {
        console.warn(' [Websocket] 未就绪', JSON.stringify(data))
        return setTimeout(() => {
          this.sendMessage(data)
        }, this.intervalTime);
      }
      console.log('%c [Websocket] ', 'background: #2888D9;', '发送消息:', JSON.stringify(data))
    }
    this.socketTask.send({
      data: JSON.stringify(data)
    })
  }

  /** 设置回调 */
  setCallback(cb) {
    this.#callback = cb
  }

  reconnect() {
    clearInterval(this.#heartbeatInterval)
    if (!this.#websocketStatus) {
      setTimeout(() => {
        this.initWebsocket()
      }, 3000);
    }
  }

  /** 主动断开连接 */
  disconnect() {
    uni.closeSocket()
    this.#websocketStatus = false
    this.#isClosed = true
    clearInterval(this.#heartbeatInterval)
  }
}